Package weasel.compiler.v2.tokentree

Source Code of weasel.compiler.v2.tokentree.WeaselTree

package weasel.compiler.v2.tokentree;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import weasel.compiler.WeaselClassCompiler;
import weasel.compiler.WeaselCompiler;
import weasel.compiler.WeaselCompilerException;
import weasel.compiler.WeaselCompilerReturn;
import weasel.compiler.WeaselInstructionList;
import weasel.compiler.WeaselKeyWordCompilerHelper;
import weasel.compiler.WeaselOperator;
import weasel.compiler.WeaselOperator.Properties;
import weasel.compiler.WeaselToken;
import weasel.compiler.WeaselTokenType;
import weasel.compiler.WeaselVariableInfo;
import weasel.compiler.keywords.WeaselKeyWord;
import weasel.interpreter.WeaselChecks;
import weasel.interpreter.WeaselGenericClass;
import weasel.interpreter.WeaselGenericClassInfo;
import weasel.interpreter.WeaselGenericMethod2;
import weasel.interpreter.WeaselModifier;
import weasel.interpreter.WeaselNativeException;
import weasel.interpreter.WeaselPrimitive;
import weasel.interpreter.bytecode.WeaselInstructionCast;
import weasel.interpreter.bytecode.WeaselInstructionCastPrimitive;
import weasel.interpreter.bytecode.WeaselInstructionPop;
import weasel.interpreter.bytecode.WeaselInstructionSaveVariable;

public abstract class WeaselTree {

  public abstract WeaselTreeAddResult add(List<WeaselToken> suffix, WeaselToken infix, List<WeaselToken> prefix, WeaselTree weaselTree, ListIterator<WeaselToken> iterator) throws WeaselCompilerException;

  public abstract WeaselCompilerReturn compile(WeaselCompiler compiler, WeaselKeyWordCompilerHelper compilerHelper, WeaselGenericClass write, WeaselGenericClass expect, WeaselGenericClass elementParent, boolean isVariable) throws WeaselCompilerException;

  public abstract String toString();
 
  public static WeaselInstructionList parseAndCompile(WeaselCompiler compiler, WeaselKeyWordCompilerHelper compilerHelper, ListIterator<WeaselToken> iterator) throws WeaselCompilerException {
   
    WeaselToken token = iterator.next();
    if(token.tokenType==WeaselTokenType.KEYWORD && ((WeaselKeyWord)token.param).compiler!=null){
      WeaselCompilerReturn wcr = ((WeaselKeyWord)token.param).compiler.compile(token, compiler, compilerHelper, iterator);
      return wcr.getInstructions(compiler, compiler.baseTypes.voidClass);
    }
    if(token.tokenType==WeaselTokenType.MODIFIER){
      return compileVarDec(token, compiler, compilerHelper, iterator);
    }
    if(token.tokenType==WeaselTokenType.IDENT){
      WeaselClassCompiler wcc = compilerHelper.getClassCompiler();
      boolean errored = false;
      try{
        wcc.readGenericClass(token, iterator);
      }catch(WeaselCompilerException e){
        while(iterator.previous()!=token);
        iterator.next();
        errored = true;
      }
      if(!errored && iterator.next().tokenType==WeaselTokenType.IDENT){
        while(iterator.previous()!=token);
        iterator.next();
        return compileVarDec(token, compiler, compilerHelper, iterator);
      }
    }
    iterator.previous();
 
    WeaselTree tree = parse(iterator, WeaselTokenType.SEMICOLON);
    if(tree!=null){
      WeaselCompilerReturn wcr = tree.compile(compiler, compilerHelper, null, new WeaselGenericClass(compiler.baseTypes.voidClass), null, false);
      return wcr.getInstructions(compiler, compiler.baseTypes.voidClass);
    }
    return null;
  }

  public static WeaselInstructionList parseAndCompileWhithVarDec(WeaselCompiler compiler, WeaselKeyWordCompilerHelper compilerHelper, ListIterator<WeaselToken> iterator) throws WeaselCompilerException {
   
    WeaselToken token = iterator.next();
    if(token.tokenType==WeaselTokenType.KEYWORD && ((WeaselKeyWord)token.param).compiler!=null){
      throw new WeaselCompilerException(token.line, "Unexpect keyword %s", token);
    }
    if(token.tokenType==WeaselTokenType.MODIFIER){
      return compileVarDec(token, compiler, compilerHelper, iterator);
    }
    if(token.tokenType==WeaselTokenType.IDENT){
      WeaselClassCompiler wcc = compilerHelper.getClassCompiler();
      boolean errored = false;
      try{
        wcc.readGenericClass(token, iterator);
      }catch(WeaselCompilerException e){
        while(iterator.previous()!=token);
        iterator.next();
        errored = true;
      }
      if(!errored && iterator.next().tokenType==WeaselTokenType.IDENT){
        while(iterator.previous()!=token);
        iterator.next();
        return compileVarDec(token, compiler, compilerHelper, iterator);
      }
    }
    iterator.previous();
 
    WeaselTree tree = parse(iterator, WeaselTokenType.SEMICOLON);
    if(tree!=null){
      WeaselCompilerReturn wcr = tree.compile(compiler, compilerHelper, null, new WeaselGenericClass(compiler.baseTypes.voidClass), null, false);
      return wcr.getInstructions(compiler, compiler.baseTypes.voidClass);
    }
    return null;
  }

 
 
  private static WeaselInstructionList compileVarDec(WeaselToken token, WeaselCompiler compiler, WeaselKeyWordCompilerHelper compilerHelper, ListIterator<WeaselToken> iterator) throws WeaselCompilerException{
    List<WeaselToken> modifiers = new ArrayList<WeaselToken>();
    while(token.tokenType==WeaselTokenType.MODIFIER){
      modifiers.add(token);
    }
    int modifier = getModifier(modifiers, WeaselModifier.FINAL);
    WeaselClassCompiler wcc = compilerHelper.getClassCompiler();
    WeaselGenericClassInfo wgci = wcc.readGenericClass(token, iterator);
    WeaselGenericClass wgc = wgci.getGenericClass(wcc.getGenericClass());
    iterator.previous();
    WeaselInstructionList instructions = new WeaselInstructionList();
    do{
      iterator.next();
      instructions.addAll(compileVar(modifier, wgc, compiler, compilerHelper, iterator));
    }while(iterator.previous().tokenType==WeaselTokenType.COMMA);
    WeaselCompiler.expect(iterator.next(), WeaselTokenType.SEMICOLON);
    return instructions;
  }
 
  private static WeaselInstructionList compileVar(int modifier, WeaselGenericClass wgc, WeaselCompiler compiler, WeaselKeyWordCompilerHelper compilerHelper, ListIterator<WeaselToken> iterator) throws WeaselCompilerException{
    WeaselToken token = iterator.next();
    WeaselCompiler.expect(token, WeaselTokenType.IDENT);
    String varName = (String)token.param;
    token = iterator.next();
    String className = wgc.getBaseClass().getByteName();
    while(token.tokenType==WeaselTokenType.OPENINDEX){
      className = "["+className;
      token = iterator.next();
      WeaselCompiler.expect(token, WeaselTokenType.CLOSEINDEX);
      token = iterator.next();
    }
    wgc = new WeaselGenericClass(compiler.getWeaselClass(className), wgc.getGenerics());
    WeaselVariableInfo wvi = compilerHelper.newVar(modifier, varName, wgc);
    if(token.tokenType==WeaselTokenType.OPERATOR && token.param == WeaselOperator.ASSIGN){
      WeaselCompilerReturn wcr = parse(iterator, WeaselTokenType.SEMICOLON, WeaselTokenType.COMMA).compile(compiler, compilerHelper, null, wgc, null, false);
      WeaselInstructionList instructions = wcr.getInstructions(compiler, wgc);
      instructions.add(token.line, new WeaselInstructionSaveVariable(wvi.pos));
      instructions.add(token.line, new WeaselInstructionPop());
      compilerHelper.writeVar(wvi);
      return instructions;
    }else{
      return new WeaselInstructionList();
    }
  }
 
  private static int getModifier(List<WeaselToken> modifiers, int allowed) throws WeaselCompilerException{
    int modifier = 0;
    for(WeaselToken modifierToken:modifiers){
      int m = (Integer) modifierToken.param;
      if((m&allowed)==0){
        throw new WeaselCompilerException(modifierToken.line, "Modifier %s is not allowed, only %s %s permitted", WeaselModifier.toString(m),
              WeaselModifier.toString(allowed), WeaselModifier.count(allowed)==1?"is":"are");
      }else if((m&modifier)!=0){
        throw new WeaselCompilerException(modifierToken.line, "Duplicated modifier %s", WeaselModifier.toString(m));
      }else{
        modifier |= m;
        try {
          WeaselChecks.checkModifier(modifier, allowed);
        } catch (WeaselNativeException e) {
          throw new WeaselCompilerException(modifierToken.line, e.getMessage());
        }
      }
    }
    return modifier;
  }
 
  public static WeaselTree parse(ListIterator<WeaselToken> iterator, WeaselTokenType...end) throws WeaselCompilerException {
   
    List<WeaselToken> tokenCache = new ArrayList<WeaselToken>();
    List<WeaselToken> tokenPrefix = new ArrayList<WeaselToken>();
    List<WeaselToken> tokenSuffix = new ArrayList<WeaselToken>();
   
    WeaselTree bottom = null;
    boolean start = true;
   
    WeaselTreeGeneric generic = null;
   
    while(iterator.hasNext()){
     
      WeaselToken token = iterator.next();
     
      if(Arrays.asList(end).contains(token.tokenType)){
       
        if(generic!=null)
          throw new WeaselCompilerException(token.line, "Expect Ident but got %s", token);
       
        while(!tokenCache.isEmpty() && ((Properties)tokenCache.get(0).param).suffix!=null){
          tokenSuffix.add(tokenCache.remove(0));
        }
       
        if(tokenCache.size()!=0){
          throw new WeaselCompilerException(token.line, "Expect suffix but got %s", tokenCache.get(0));
        }
       
        if(!tokenSuffix.isEmpty()){
          WeaselTreeAddResult wtar = bottom.add(tokenSuffix, null, null, null, iterator);
          bottom = wtar.newTree;
        }
       
        tokenPrefix.clear();
        tokenSuffix.clear();
        tokenCache.clear();
       
        break;
       
      }else{
     
        if(token.tokenType==WeaselTokenType.KEYWORD && token.param==WeaselKeyWord.INSTANCEOF){
          WeaselToken t = iterator.next();
          WeaselCompiler.expect(t, WeaselTokenType.IDENT);
          String className = (String)t.param;
          t = iterator.next();
          while(t.tokenType==WeaselTokenType.OPERATOR && t.param==WeaselOperator.ELEMENT){
            t = iterator.next();
            WeaselCompiler.expect(t, WeaselTokenType.IDENT);
            className += "."+(String)t.param;
            t = iterator.next();
          }
          if(t.tokenType==WeaselTokenType.OPERATOR && t.param==WeaselOperator.LESS){
            generic = new WeaselTreeGeneric(iterator);
            if(generic.close)
              throw new WeaselCompilerException(t.line, "To many >");
          }else{
            iterator.previous();
          }
          token = new WeaselInstanceofToken(token.line, className, generic);
          generic = null;
        }
       
        if(token.tokenType==WeaselTokenType.COMMA){
          token = new WeaselToken(WeaselTokenType.OPERATOR, token.line, WeaselOperator.COMMA);
        }
       
        if(token.tokenType==WeaselTokenType.QUESTIONMARK){
         
          if(generic!=null)
            throw new WeaselCompilerException(token.line, "Expect Ident but got ?:");
         
          while(!tokenCache.isEmpty() && ((Properties)tokenCache.get(0).param).suffix!=null){
            tokenSuffix.add(tokenCache.remove(0));
          }
         
          if(tokenCache.size()!=0){
            throw new WeaselCompilerException(token.line, "Expect suffix but got %s", tokenCache.get(0));
          }
         
          if(!tokenSuffix.isEmpty()){
            WeaselTreeAddResult wtar = bottom.add(tokenSuffix, null, null, null, iterator);
            bottom = wtar.newTree;
          }
         
          WeaselTree tree = parse(iterator, WeaselTokenType.COLON);
         
          WeaselTreeCondition wtc = new WeaselTreeCondition(tree, token);
         
          WeaselTreeAddResult wtar = wtc.setLeft(bottom);
         
          bottom = wtar.newTree;
         
          start = true;
         
        }else if(token.tokenType == WeaselTokenType.OPERATOR){
         
          if(generic!=null)
            throw new WeaselCompilerException(token.line, "Expect Ident but got %s", token);
         
          tokenCache.add(token);
       
          if(token.param == WeaselOperator.ELEMENT){
            WeaselToken wtoken = iterator.next();
            if(wtoken.tokenType == WeaselTokenType.OPERATOR && wtoken.param ==WeaselOperator.LESS) {
              generic = new WeaselTreeGeneric(iterator);
              token = iterator.previous();
              if(generic.close){
                throw new WeaselCompilerException(token.line, "Expect Ident but got >");
              }
            }else{
              iterator.previous();
            }
          }
         
        }else{
         
          if(generic!=null && token.tokenType != WeaselTokenType.IDENT)
            throw new WeaselCompilerException(token.line, "Expect ident after generic but got %s", token);
         
          boolean isCast = false;
         
          if(token.tokenType==WeaselTokenType.OPENBRACKET){
            WeaselToken token2 = iterator.next();
            String className = "";
            if(token2.tokenType==WeaselTokenType.IDENT){
              isCast = true;
              className = (String)token2.param;
              token2 = iterator.next();
              while(token2.tokenType==WeaselTokenType.OPERATOR && token2.param == WeaselOperator.ELEMENT){
                token2 = iterator.next();
                if(token2.tokenType!=WeaselTokenType.IDENT){
                  isCast = false;
                  break;
                }
                className += "."+(String)token2.param;
                token2 = iterator.next();
              }
              if(token2.tokenType==WeaselTokenType.OPERATOR && token2.param == WeaselOperator.LESS){
                try{
                  generic = new WeaselTreeGeneric(iterator);
                  token2 = iterator.next();
                }catch(WeaselCompilerException e){
                  isCast = false;
                }
              }
              if(isCast && token2.tokenType!=WeaselTokenType.CLOSEBRACKET){
                isCast = false;
              }
            }
            if(isCast){
              tokenCache.add(new WeaselCastToken(token.line, className, generic));
            }else{
              while(iterator.previous() != token);
              iterator.next();
            }
            generic = null;
          }
         
          if(!isCast){
           
            if(start){
             
              while(!tokenCache.isEmpty() && ((Properties)tokenCache.get(tokenCache.size()-1).param).prefix!=null){
                tokenPrefix.add(tokenCache.remove(tokenCache.size()-1));
              }
             
              if(!tokenCache.isEmpty()){
                throw new WeaselCompilerException(token.line, "Expect prefix but got %s", tokenCache.get(0));
              }
             
              if(token.tokenType==WeaselTokenType.OPENBRACKET){
                WeaselTree add = parse(iterator, WeaselTokenType.CLOSEBRACKET);
                if(tokenPrefix.isEmpty()){
                  if(bottom==null){
                    bottom = new WeaselTreeTop(add, iterator);
                  }else{
                    bottom.add(null, null, null, new WeaselTreeTop(add, iterator), iterator);
                  }
                }else{
                  if(bottom==null){
                    bottom = new WeaselTreeLevel(((Properties)tokenPrefix.get(0).param).priority);
                  }
                  WeaselTreeAddResult wtar = bottom.add(null, null, tokenPrefix, add, iterator);
                  bottom = wtar.newTree;
                }
              }else{
                WeaselTree add = new WeaselTreeTop(token, null, iterator);
                if(tokenPrefix.isEmpty()){
                  if(bottom==null){
                    bottom = add;
                  }else{
                    bottom.add(null, null, null, add, iterator);
                  }
                }else{
                  if(bottom==null){
                    bottom = new WeaselTreeLevel(((Properties)tokenPrefix.get(0).param).priority);
                  }
                  WeaselTreeAddResult wtar = bottom.add(null, null, tokenPrefix, add, iterator);
                  bottom = wtar.newTree;
                }
              }
             
              tokenPrefix.clear();
              tokenSuffix.clear();
              tokenCache.clear();
             
              start = false;
             
            }else{
             
              if(tokenCache.size()==0){
                throw new WeaselCompilerException(token.line, "Expect %s before %s", Arrays.toString(end), token);
              }
             
              while(!tokenCache.isEmpty() && ((Properties)tokenCache.get(0).param).suffix!=null){
                tokenSuffix.add(tokenCache.remove(0));
              }
             
              if(tokenCache.isEmpty() && !tokenPrefix.isEmpty()){
                while(true){
                  tokenCache.add(0, tokenPrefix.remove(tokenPrefix.size()-1));
                  if(((Properties)tokenCache.get(0).param).infix!=null){
                    break;
                  }
                }
              }
             
              while(tokenCache.size()>1 && ((Properties)tokenCache.get(tokenCache.size()-1).param).prefix!=null){
                tokenPrefix.add(0, tokenCache.remove(tokenCache.size()-1));
              }
             
              if(tokenCache.size()==0){
                throw new WeaselCompilerException(token.line, "Expect %s before %s", Arrays.toString(end), token);
              }
             
              if(tokenCache.size()>1){
                throw new WeaselCompilerException(tokenCache.get(1).line, "Expect suffix or variable but got %s", tokenCache.get(1));
              }
             
              for(WeaselToken token1:tokenSuffix){
                token1.param = ((Properties)token1.param).suffix;
                if(token1.param==null)
                  throw new NullPointerException();
              }
             
              for(WeaselToken token1:tokenCache){
                token1.param = ((Properties)token1.param).infix;
                if(token1.param==null)
                  throw new NullPointerException();
              }
             
              for(WeaselToken token1:tokenPrefix){
                token1.param = ((Properties)token1.param).prefix;
                if(token1.param==null)
                  throw new NullPointerException();
              }
             
              WeaselTree add;
              if(token.tokenType==WeaselTokenType.OPENBRACKET){
                add = parse(iterator, WeaselTokenType.CLOSEBRACKET);
                add = new WeaselTreeTop(add, iterator);
              }else{
                add = new WeaselTreeTop(token, generic, iterator);
              }
             
              WeaselTreeAddResult wtar = bottom.add(tokenSuffix, tokenCache.get(0), tokenPrefix, add, iterator);
              bottom = wtar.newTree;
             
              tokenPrefix.clear();
              tokenSuffix.clear();
              tokenCache.clear();
           
            }
          }
        }
      }
    }
   
    return bottom;
   
  }

  public static WeaselGenericClass autoCast(WeaselCompiler compiler, WeaselGenericClass wc1, WeaselGenericClass wc2, int line, WeaselInstructionList instructions, boolean b) throws WeaselCompilerException{
    if(!wc1.getBaseClass().isPrimitive() && wc2.getBaseClass().isPrimitive()){
      wc2 = new WeaselGenericClass(compiler.getWeaselClass(WeaselPrimitive.getWrapper(wc2.getBaseClass())));
      instructions.add(line, new WeaselInstructionCast(wc2.getBaseClass().getByteName()));
    }else if(wc1.getBaseClass().isPrimitive() && wc2.getBaseClass().isPrimitive()){
      if(wc1.getBaseClass()!=wc2.getBaseClass()){
        boolean canCast = WeaselPrimitive.canCastAutoTo(wc1.getBaseClass(), wc2.getBaseClass());
        if(canCast){
          instructions.add(line, new WeaselInstructionCastPrimitive(WeaselPrimitive.getPrimitiveID(wc2.getBaseClass())));
          return wc2;
        }else if(b){
          throw new WeaselCompilerException(line, "Types %s and %s are not compatible", wc1, wc2);
        }
      }
    }
    return wc1;
  }
 
  public static WeaselParameterCompileReturn compileParamList(int line, String methodName, WeaselCompiler compiler, WeaselKeyWordCompilerHelper compilerHelper, WeaselTree func, List<WeaselGenericMethod2> methods) throws WeaselCompilerException {
    WeaselCompilerReturn wcr;
    WeaselInstructionList instructions = new WeaselInstructionList();
    WeaselGenericMethod2 method;
    if(func instanceof WeaselTreeLevel){
      WeaselTreeLevel treeLevel = (WeaselTreeLevel) func;
      if(treeLevel.levelPriority == 0){
        int param=treeLevel.level.size();
        Iterator<WeaselGenericMethod2> iterator = methods.iterator();
        while(iterator.hasNext()){
          if(iterator.next().getGenericParams().length!=param)
            iterator.remove();
        }
        WeaselGenericClass expect = null;
        if(methods.isEmpty())
          throw new WeaselCompilerException(line, "No method %s found with %s params", param);
        List<WeaselGenericClass> params = new ArrayList<WeaselGenericClass>();
        for(int i=0; i<param; i++){
          if(methods.size()==1)
            expect = methods.get(0).getGenericParams()[i];
          wcr = treeLevel.level.get(i).compile(compiler, compilerHelper, null, expect, null, false);
          instructions.addAll(wcr.getInstructions());
          params.add(wcr.getReturnType());
        }
        iterator = methods.iterator();
        while(iterator.hasNext()){
          WeaselGenericMethod2 m=iterator.next();
          for(int i=0; i<param; i++){
            if(params.get(i)!=null && !params.get(i).canCastTo(m.getGenericParams()[i]))
              iterator.remove();
          }
        }
        if(methods.isEmpty()){
          throw new WeaselCompilerException(line, "No method %s found with for params %s", methodName, params);
        }
        if(methods.size()==1){
          method = methods.get(0);
        }else{
          throw new WeaselCompilerException(line, "Not supported now");
        }
        return new WeaselParameterCompileReturn(instructions, method);
      }
    }
    if(func==null){
      method = null;
      for(WeaselGenericMethod2 m:methods){
        if(m.getGenericParams().length==0){
          method = m;
          break;
        }
      }
      if(method==null){
        throw new WeaselCompilerException(line, "No method %s found with no params", methodName);
      }
    }else{
      Iterator<WeaselGenericMethod2> iterator = methods.iterator();
      while(iterator.hasNext()){
        if(iterator.next().getGenericParams().length!=1)
          iterator.remove();
      }
      WeaselGenericClass expect = null;
      if(methods.isEmpty())
        throw new WeaselCompilerException(line, "No method %s found with one param", methodName);
      if(methods.size()==1)
        expect = methods.get(0).getGenericParams()[0];
      wcr = func.compile(compiler, compilerHelper, null, expect, null, false);
      instructions.addAll(wcr.getInstructions());
      iterator = methods.iterator();
      while(iterator.hasNext()){
        WeaselGenericMethod2 m=iterator.next();
        if(!wcr.getReturnType().canCastTo(m.getGenericParams()[0]))
          iterator.remove();
      }
      if(methods.isEmpty()){
        throw new WeaselCompilerException(line, "No method %s found with for param %s", methodName, wcr.getReturnType());
      }
      if(methods.size()==1){
        method = methods.get(0);
      }else{
        throw new WeaselCompilerException(line, "Not supported now");
      }
    }
    return new WeaselParameterCompileReturn(instructions, method);
  }
 
}
TOP

Related Classes of weasel.compiler.v2.tokentree.WeaselTree

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.